


	package fatboy.test;

	import java.io.File;
	import java.io.FileNotFoundException;

	import java.io.PrintStream;
	import java.util.List;
	import java.util.Scanner;

	import junit.framework.Assert;

	import org.junit.Test;

	import fatboy.addons.FinalListener;
	import fatboy.addons.Listener;
	import fatboy.hypeerweb.Connection;
	import fatboy.hypeerweb.Node;


	/**
	 * testing the broadcastWithAck usecase based off of the specs
	 * @author Jack
	 *
	 */
	public class testBroadcastWithAck {
		/**
		 * see that final listener behaves properly
		 */
		@Test
		public void testFinalListener(){
			File output = getOutput();
			Listener test = new FinalListener(1,null);
			verifyOutputBad(output);
			test.inc(1);
			verifyOutput(output);
		}
		/**
		 * make sure output hasn't finished
		 * @param output
		 */
		private void verifyOutputBad(File output) {
			Scanner scan = null;
			try {
				scan = new Scanner(output);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			boolean foundIt = false;
			while(scan.hasNextLine()){
				foundIt |= scan.nextLine().contains("all nodes have reported");
			}
			if(foundIt){
				Assert.fail();
			}
			
		}
		/**
		 * makes sure it functions properly if it is the only node in the web
		 * expected output: nothing followed by a all done printout
		 */
		@Test
		public void singleNodeTestOfBroadCast(){
			
			Connection connect = setupWeb(1);
			
			List<Node> web = connect.getAllNodes();
			for(Node n : web){
				File output = getOutput();
				connect.broadcastWithAck(n);
				verifyOutput(output);
			}
		}
		/**
		 * checks that broadcast works from any node in a two node tree  
		 * expected output: printout at node 1 then at node 0
		 *  followed by a all done printout
		 */
		@Test
		public void twoNodeTestOfBroadCast(){
			final int two = 2;
			Connection connect = setupWeb(two);
			
			List<Node> web = connect.getAllNodes();
			for(Node n : web){
				File output = getOutput();
				connect.broadcastWithAck(n);
				verifyOutput(output);
			}
		}
		/**
		 * tests that the broadcast sends the message to every node and all respond in the tree
		 *  for any node a perfect hypeerweb
		 */
		@Test
		public void perfetHypeerWebState(){
			final int sixtyfour = 64;
			Connection connect = setupWeb(sixtyfour);
			
			List<Node> web = connect.getAllNodes();
			for(Node n : web){
				File output = getOutput();
				connect.broadcastWithAck(n);
				verifyOutput(output);
			}
		}
		/**
		 * tests that the broadcast sends the message to every node and all respond in the tree
		 *  for any node a incomplete hypeerweb
		 */
		@Test
		public void incompleteHypeerWebState(){
			final int fiftythree = 53;
			Connection connect = setupWeb(fiftythree);
			
			List<Node> web = connect.getAllNodes();
			for(Node n : web){
				File output = getOutput();
				connect.broadcastWithAck(n);
				verifyOutput(output);
			}
		}
		private File getOutput() {
			PrintStream ps = null;
			File output = new File("test.txt");
			try {
				ps = new PrintStream(output);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			System.setOut(ps);
			return output;
		}
		static void verifyOutput(File output) {
			Scanner scan = null;
			try {
				scan = new Scanner(output);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			boolean foundIt = false;
			while(scan.hasNextLine()){
				foundIt |= scan.nextLine().contains("all nodes have reported");
			}
			if(!foundIt){
				Assert.fail();
			}
			
		}
		private Connection setupWeb(int i){
			Connection connect = new Connection();
			for(int j = 0; j < i; j++){
				connect.addNode(j);
			}
			return connect;
		}
	}


